package xxl.signals.base.natives 
{
	import flash.events.Event;
	import flash.events.IEventDispatcher;
	import xxl.signals.util.SignalUtil;
	/**
	 * ...
	 * @author XXL
	 */
	public class NativeMappedSignal extends NativeRelaySignal 
	{
		protected var _mappingFunction:Function = null;
		protected var defaultMappingArgs:Array;
		
		public function NativeMappedSignal(target:IEventDispatcher = null, eventType:String = "", eventClass:Class = null, ...mappedTypes) 
		{
			super(target, eventType, eventClass);
			valueClasses = mappedTypes;
		}
		
		public function get mappingFunction():Function
		{
			return _mappingFunction;
		}
		
		override public function set valueClasses(value:Array):void 
		{
			SignalUtil.VerifyValueClasses(value);
			_valueClasses = value ? value.concat() : [];
		}
		
		public function mapTo(...objectListOrFunction):NativeMappedSignal
		{
			if (objectListOrFunction.length == 1 && objectListOrFunction[0] is Function)
			{
				_mappingFunction = objectListOrFunction[0] as Function;
				if (mappingFunction.length > 1)
				{
					throw new ArgumentError("Mapping方法只能接受最多一个Event参数");
				}
			}
			else
			{
				defaultMappingArgs = objectListOrFunction;
				_mappingFunction = defaultMappingFunction;
			}
			return this;
		}
		
		final protected function defaultMappingFunction():Array
		{
			return defaultMappingArgs;
		}
		
		protected function mapEvent(eventFromTarget:Event):Object
		{
			if (mappingFunction != null)
			{
				if (mappingFunction.length == 1)
				{
					return mappingFunction(eventFromTarget);
				}
				else
				{
					return mappingFunction();
				}
			}
			else if (valueClasses.length == 0)
			{
				return [];
			}
			throw new ArgumentError("设置了valueClasses但是mappingFunction为空");
		}
		
		override public function dispatchEvent(event:Event):Boolean 
		{
			const mappedData:Object = mapEvent(event);
			if (mappedData is Array)
			{
				const valueObjects:Array = mappedData as Array;
				SignalUtil.VerifyDispatch(valueClasses, valueObjects);
			}
			else 
			{
				SignalUtil.VerifyDispatch(valueClasses, [mappedData]);
			}
			return super.dispatchEvent(event);
		}
		
		override protected function onNativeEvent(e:Event):void 
		{
			if (sortFlag)
			{
				sortFlag = false;
				slots = slots.sortOn("priority", Array.NUMERIC);
			}
			var i:int;
			const mappedData:Object = mapEvent(e);
			if (mappedData is Array)
			{
				if (valueClasses.length == 1 && valueClasses[0] == Array)
				{
					for (i = slots.length; i--; )
					{
						slots[i].execute1(mappedData);
					}
				}
				else
				{
					const mappedDataArray:Array = mappedData as Array;
					for (i = slots.length; i--; )
					{
						slots[i].execute(mappedDataArray);
					}
				}
			}
			else
			{
				for (i = slots.length; i--; )
				{
					slots[i].execute1(mappedData);
				}
			}
		}
		
	}

}